package service

import (
	"delivery-server/utils"
	"delivery-server/utils/response"
	"github.com/go-xorm/xorm"
	"time"
)

// UserService 用户服务
type UserService interface {

	// QueryUserIdByUsernameAndPassword 根据用户名和密码获取用户
	QueryUserIdByUsernameAndPassword(username, password string) (string, bool)

	// QueryUserIdByUsername 根据用户名查询id
	QueryUserIdByUsername(username string) (string, bool)

	// InsertUsernameAndPassword 在user表插入username和password，成功返回true
	InsertUsernameAndPassword(username, password string) bool

	// RegisterTransaction 注册事务 返回值：true-注册成功、false-用户名已被使用
	RegisterTransaction(username, password string) int

	// QueryInformation 查询用户信息
	QueryInformation(userId int) (results []map[string]string, err error)

	// UpdateInformation 修改用户信息
	UpdateInformation(userId, sex, placeId int, nickname string) (err error)

	// QueryDish 查询菜品
	QueryDish(categoryId int) (results []map[string]string, err error)

	// TryToBuy 购买菜品
	TryToBuy(userId, dishId, quantity, money int) (code int)

	// AllWaitOrder 所有未接取订单
	AllWaitOrder(userId int) (results []map[string]string, err error)

	// AllProgressOrder 所有派送中订单
	AllProgressOrder(userId int) (results []map[string]string, err error)

	// AllFinishOrder 所有已完成订单
	AllFinishOrder(userId int) (results []map[string]string, err error)

	// AllEvaluateOrder 所有已评价订单
	AllEvaluateOrder(userId int) (results []map[string]string, err error)

	// GetNickname 获取用户昵称
	GetNickname(userId int) (results []map[string]string, err error)
}

// NewUserService 创建一个新的用户服务对象
func NewUserService(engine *xorm.Engine) UserService {
	return &userService{
		Engine: engine,
	}
}

// 用户服务结构体
type userService struct {
	Engine *xorm.Engine
}

// QueryUserIdByUsernameAndPassword 根据用户名和密码获取用户
func (us userService) QueryUserIdByUsernameAndPassword(username, password string) (string, bool) {

	// 根据用户名和密码来查询id
	sqlStr := "SELECT id FROM user WHERE username = ? and password = ?"
	results, err := us.Engine.QueryString(sqlStr, username, password)
	if err != nil {
		panic(err.Error())
	}

	// 检测是否找到匹配结果
	if len(results) == 1 {
		return results[0]["id"], true
	}
	return "", false
}

// QueryUserIdByUsername 根据用户名查询id
func (us userService) QueryUserIdByUsername(username string) (string, bool) {

	// 根据用户名查询id
	sqlStr := "SELECT id FROM user WHERE username = ?"
	results, err := us.Engine.QueryString(sqlStr, username)
	if err != nil {
		panic(err.Error())
	}

	// 检测是否找到匹配结果
	if len(results) == 1 {
		return results[0]["id"], true
	}
	return "", false
}

// InsertUsernameAndPassword 在user表插入username和password
func (us userService) InsertUsernameAndPassword(username, password string) bool {

	// 在user表插入username和password
	sqlStr := "INSERT INTO user(username, password) VALUES (?, ?)"
	_, err := us.Engine.Exec(sqlStr, username, password)
	return err == nil
}

// RegisterTransaction 注册事务
func (us userService) RegisterTransaction(username, password string) int {

	// 创建session对象
	session := us.Engine.NewSession()
	defer session.Close()

	// 事务开始
	err := session.Begin()
	if err != nil {
		panic(err.Error())
		return response.ServerErrCode
	}

	// 查询该用户名是否已存在
	_, exist := us.QueryUserIdByUsername(username)

	// 用户名已存在
	if exist {
		err = session.Rollback()
		if err != nil {
			panic(err.Error())
		}
		return response.UsernameExistCode
	}

	// 获取插入结果
	loginSuccess := us.InsertUsernameAndPassword(username, password)

	// 如果插入数据失败
	if !loginSuccess {
		err = session.Rollback()
		if err != nil {
			panic(err.Error())
		}
		return response.ServerErrCode
	}

	// 提交事务
	err = session.Commit()
	if err != nil {
		return response.ServerErrCode
	}

	return response.SuccessCode
}

// QueryInformation 查询用户信息
func (us userService) QueryInformation(userId int) (results []map[string]string, err error) {

	sqlStr := "SELECT username, nickname, sex, balance, place_id FROM user WHERE id = ?"
	results, err = us.Engine.QueryString(sqlStr, userId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// UpdateInformation 修改用户信息
func (us userService) UpdateInformation(userId, sex, placeId int, nickname string) (err error) {

	sqlStr := "UPDATE user SET nickname = ?, sex = ?, place_id = ? WHERE id = ?"
	_, err = us.Engine.QueryString(sqlStr, nickname, sex, placeId, userId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// QueryDish 查询菜品
func (us userService) QueryDish(categoryId int) (results []map[string]string, err error) {
	sqlStr := "SELECT dish.id AS id, dish.name AS name, restaurant.id AS restaurantId, price," +
		" restaurant.name AS restaurantName" +
		" FROM dish, restaurant WHERE dish.invalidity = 0 AND category_id = ? AND dish.restaurant_id = restaurant.id"
	results, err = us.Engine.QueryString(sqlStr, categoryId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// TryToBuy 购买菜品
func (us userService) TryToBuy(userId, dishId, quantity, money int) (code int) {

	session := us.Engine.NewSession()
	defer session.Close()

	// 事务开始
	err := session.Begin()
	if err != nil {
		return response.ServerErrCode
	}

	// 获取用户信息
	sqlStr := "SELECT balance, place_id FROM user WHERE id = ?"
	users, err := us.Engine.QueryString(sqlStr, userId)
	if err != nil {
		return response.ServerErrCode
	}
	if len(users) == 0 {
		return response.DataErrCode
	}

	// 获取用户地点
	placeId := users[0]["place_id"]
	if placeId == "" {
		return response.PlaceNullCode
	}

	// 获取菜品信息
	sqlStr = "SELECT restaurant_id, price FROM dish WHERE invalidity = 0 AND id = ?"
	dishes, err := us.Engine.QueryString(sqlStr, dishId)
	if err != nil {
		return response.ServerErrCode
	}
	// 菜品不存在
	if len(dishes) == 0 {
		return response.DishNotExistCode
	}

	// 获取用户余额、餐馆id、菜品价格
	balance := users[0]["balance"]
	restaurantId := dishes[0]["restaurant_id"]
	price := dishes[0]["price"]
	paramsInt, convertSuccess := utils.CheckInteger(balance, placeId, restaurantId, price)
	if !convertSuccess {
		return response.ServerErrCode
	}

	// 余额检测
	if paramsInt[balance] < money {
		return response.MoneyLackCode
	}

	// 价格检测
	if paramsInt[price]*quantity != money {
		return response.MoneyErrCode
	}

	// 用户扣款
	sqlStr = "UPDATE user SET balance = balance - ? WHERE id = ?"
	_, err = us.Engine.Exec(sqlStr, money, userId)
	if err != nil {
		_ = session.Rollback()
		return response.ServerErrCode
	}

	// 餐厅获款
	sqlStr = "UPDATE restaurant SET property = property - ? WHERE id = ?"
	_, err = us.Engine.Exec(sqlStr, money, paramsInt[restaurantId])
	if err != nil {
		_ = session.Rollback()
		return response.ServerErrCode
	}

	// 创建订单
	sqlStr = "INSERT INTO `order`(price, quantity, created_time, user_id, restaurant_id, dish_id, user_place)" +
		" VALUES (?, ?, ?, ?, ?, ?, ?)"
	_, err = us.Engine.Exec(sqlStr, paramsInt[price], quantity, time.Now(), userId,
		paramsInt[restaurantId], dishId, paramsInt[placeId])
	if err != nil {
		_ = session.Rollback()
		return response.ServerErrCode
	}

	// 提交
	err = session.Commit()
	if err != nil {
		return response.ServerErrCode
	}

	return response.SuccessCode
}

// AllWaitOrder 所有未接取订单
func (us userService) AllWaitOrder(userId int) (results []map[string]string, err error) {
	sqlStr := "SELECT `order`.id AS orderId, dish.name AS dishName, dish.price AS dishPrice, quantity" +
		" FROM `order`, dish WHERE `order`.dish_id = dish.id" +
		" AND `order`.user_id = ? AND staffer_id IS NULL"
	results, err = us.Engine.QueryString(sqlStr, userId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// AllProgressOrder 所有派送中订单
func (us userService) AllProgressOrder(userId int) (results []map[string]string, err error) {
	sqlStr := "SELECT `order`.id AS orderId, dish.name AS dishName, dish.price AS dishPrice, quantity" +
		" FROM `order`, dish WHERE `order`.dish_id = dish.id" +
		" AND staffer_id IS NOT NULL AND finished_time IS NULL AND `order`.user_id = ?"
	results, err = us.Engine.QueryString(sqlStr, userId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// AllFinishOrder 所有完成订单
func (us userService) AllFinishOrder(userId int) (results []map[string]string, err error) {
	sqlStr := "SELECT `order`.id AS orderId, dish.name AS dishName, dish.price AS dishPrice, quantity," +
		" `order`.dish_id AS dishId, `order`.restaurant_id AS restaurantId, staffer_id AS stafferId" +
		" FROM `order`, dish WHERE `order`.dish_id = dish.id" +
		" AND user_id = ? AND finished_time IS NOT NULL AND is_evaluate = 0"
	results, err = us.Engine.QueryString(sqlStr, userId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// AllEvaluateOrder 所有已评价订单
func (us userService) AllEvaluateOrder(userId int) (results []map[string]string, err error) {
	sqlStr := "SELECT `order`.id AS orderId, dish.name AS dishName, dish.price AS dishPrice, quantity" +
		" FROM `order`, dish WHERE `order`.dish_id = dish.id" +
		" AND user_id = ? AND finished_time IS NOT NULL AND is_evaluate = 1"
	results, err = us.Engine.QueryString(sqlStr, userId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// GetNickname 获取用户昵称
func (us userService) GetNickname(userId int) (results []map[string]string, err error) {
	sqlStr := "SELECT nickname FROM user WHERE id = ?"
	results, err = us.Engine.QueryString(sqlStr, userId)
	if err != nil {
		panic(err.Error())
	}
	return
}
